#include<iostream>
#include<vector>
#include<unordered_map>
#include<set>
#include<memory>
#include<cstdlib>
#include<ctime>
#include<algorithm>
#include<utility>
#include <fstream>
#include <cassert>
#include<random>
#include<cstring>
#include "readfile.cpp"
using namespace std;

// 元件基类，包括电流源，电压源，电阻，电容，电感
class Component {
public:
    string name;  //名称
    int n1;
    int n2;       //两端节点,在每个元件的构造函数中应当将n1和n2的初始值设置为-1，代表节点无效
    void setNodes(int n_1, int n_2)   //设置两端节点
    {
        n1 = n_1;
        n2 = n_2;
    }
    void resetNode() {n1 = n2 = -1;}  //重置两个节点为无效，一般配合以下changeNode函数使用
    void changeNode(int n)   //改变某个节点
    {
        if(n1 == -1)
            n1 = n;
        else if (n2 == -1)
            n2 = n;
        else
            n1 = n;
    }

    virtual string getNetlistEntry(int preNumNodes) const = 0;   //返回网表格式

};

// 电阻
class Resistor : public Component {
private:
    double resistance;  //电阻值，单位Ω，参考范围50-100 Ω
public:
    Resistor(double r, int num)
    { 
        resistance = r;
        name = "R"+to_string(num);
        resetNode();
    }
    string getNetlistEntry(int preNumNodes) const override {
        return name + " " + to_string(n1 + preNumNodes) + " " + to_string(n2 + preNumNodes) + " " + to_string(resistance);
    }
};

// 电容
class Capacitor : public Component {
private:
    double capacitance;  //电容值，单位F，参考范围0.001-0.1F
public:
    Capacitor(double c, int num) 
    { 
        capacitance = c;
        name = "C"+to_string(num);
        resetNode();
    }
    string getNetlistEntry(int preNumNodes) const override {
        return name + " " + to_string(n1 + preNumNodes) + " " + to_string(n2 + preNumNodes) + " " + to_string(capacitance);
    }
};

// 电感
class Inductor : public Component {
private:
    double inductance;   //电感值，单位H，参考范围0.01-1H
public:
    Inductor(double l, int num)
    { 
        inductance = l;
        name = "L"+to_string(num);
        resetNode();
    }
    string getNetlistEntry(int preNumNodes) const override {
        return name + " " + to_string(n1 + preNumNodes) + " " + to_string(n2 + preNumNodes) + " " + to_string(inductance);
    }
};
// 电压源
class VoltageSource : public Component {
private:
//规定n1是正极，n2是负极
    double voltage;
public:
    bool isShorted;    //标记电压源是否被短路
    VoltageSource(double v, int num)
    { 
        voltage = v;
        name = "V"+to_string(num);
        resetNode();
        isShorted = false;
    }
    string getNetlistEntry(int preNumNodes) const override {
        return name + " " + to_string(n1 + preNumNodes) + " " + to_string(n2 + preNumNodes) + " DC " + to_string(voltage);
    }
};

// 电流源
class CurrentSource : public Component {
private:
//规定n1是正极，n2是负极
    double current;
public:
    CurrentSource(double i, int num)
    { 
        current = i;
        name = "I" + to_string(num);
        resetNode();
    }
    string getNetlistEntry(int preNumNodes) const override {
        return name + " " + to_string(n1 + preNumNodes) + " " + to_string(n2 + preNumNodes) + " DC " + to_string(current);
    }
};

// Circuit相当于一个环路
class Circuit {
private:
    unordered_map<int, vector<Component*>> adjacencyList;  //邻接表，用于存储节点与其相连的对应元件
    int numVoltageSources;  //电压源数目
    int numCurrentSources;  //电流源数目
    int numResistors;    //电阻数目
    int numCapacitors;    //电容数目
    int numInductors;     //电感数目

    VoltageSource** list_VS;   //存储电压源
    CurrentSource** list_CS;   //存储电流源
    Resistor** list_R;  //存储电阻
    Capacitor** list_C;   //存储电容
    Inductor** list_L;  //存储电感 

    int numNodes;    //实际节点数量
    bool isOpen;     //标记是否开路
    int preNumNodes; //已用节点数量
    int preNumVoltS; //已用电压源数目
    int preNumCurrS; //已用电流源数目
    int preNumR; //已用电阻数目
    int preNumC; //已用电容数目
    int preNumL; //已用电感数目

    void DFS(int node, bool visited[], vector<int>& currentComponent) //DFS算法，用于寻找电路图中的连通分量
    {
        visited[node] = true;   //访问过，进行标记
        currentComponent.push_back(node);  //将节点node加入当前连通分量
        for(int i = 0; i < adjacencyList[node].size(); i++)
        {
            int neighbor = (adjacencyList[node][i]->n1 == node)?adjacencyList[node][i]->n2:adjacencyList[node][i]->n1;  //取相邻节点
            if(visited[neighbor] == false)       //如果未访问过，则进行DFS
                DFS(neighbor,visited,currentComponent);
        }
    }

    void connectSeparateCircuit()  //连通各个连通分量的函数：初步随机生成Circuit后，从图论上来看，很可能整个图不是一个连通分量，即很可能会有独立的连通分量，所以借助DFS算法找到所有连通分量，并通过此函数连接
    {
        //srand(time(0));  //取随机数种子
        int nNodes = adjacencyList.size();
        bool visited[nNodes];    //标记节点是否已经被访问
        for(int i = 0; i < nNodes; i++)
            visited[i] = false;
        vector<int> representNodes_1;  //记录各个连通分量代表的节点,每个连通分量取2个代表节点，以保证连通分量连接后能形成一个环
        representNodes_1.clear();
        vector<int> representNodes_2;  //记录各个连通分量代表的节点,每个连通分量取2个代表节点，以保证连通分量连接后能形成一个环
        representNodes_2.clear();
        vector<int> currentComponent; //存储当前连通分量的所有结点

        for(int i = 0; i < adjacencyList.size(); i++)
            if(visited[i] == false)
            {
                currentComponent.clear();   //清空当前连通分量所有节点
                DFS(i,visited,currentComponent);

                int temp_1 = rand()%currentComponent.size();     //在当前连通分量的所有节点中随机取两个不同节点作为代表节点
                int temp_2 = rand()%currentComponent.size();
                while(temp_1 == temp_2)      //保证取到的两个节点不同
                {
                    temp_1 = rand()%currentComponent.size();     
                    temp_2 = rand()%currentComponent.size();
                }
                representNodes_1.push_back(currentComponent[temp_1]);
                representNodes_2.push_back(currentComponent[temp_2]);
            }
        //接下来分别将两组代表节点合并
        if(representNodes_1.size() == 1)   //如果代表节点数量为1，说明原图只有一个连通分量，直接返回
            return;
        for(int i = 1; i < representNodes_1.size(); i++)
            mergeNodes(representNodes_1[0],representNodes_1[i]);
        for(int i = 1; i < representNodes_2.size(); i++)
            mergeNodes(representNodes_2[0],representNodes_2[i]);
        
        deleteEmptyNodes();         //最后删除空节点
    }

    void deleteEmptyNodes()    //删除邻接表中的所有空节点
    {
        unordered_map<int, vector<Component*>> temp_adjList;  //创建一个空的邻接表
        int count = 0;
        for(int i = 0; i < adjacencyList.size(); i++)   //遍历找出非空节点
            if(adjacencyList[i].size() != 0)   //copy非空节点
                temp_adjList[count++] = adjacencyList[i];
        adjacencyList = temp_adjList;    //整个邻接表复制过来，相当于完成了空节点的删除

        //现在对所有元件对象中储存的两端节点n1和n2进行更新

        for(int i = 0; i < numResistors; i++)  
            list_R[i]->resetNode();
        for(int i = 0; i < numCapacitors; i++)
            list_C[i]->resetNode();
        for(int i = 0; i < numInductors; i++)
            list_L[i]->resetNode();
        for(int i = 0; i < numVoltageSources; i++)
            list_VS[i]->resetNode();
        for(int i = 0; i < numCurrentSources; i++)
            list_CS[i]->resetNode();
        
        for(int i = 0; i < adjacencyList.size(); i++)
            for(int j = 0; j < adjacencyList[i].size(); j++)  //遍历每个节点的每个连接的元件
                adjacencyList[i][j]->changeNode(i);
    }

    void mergeNodes(int node1, int node2)   //合并node1和node2两个节点成为node1（规定输入时node1<node2，且node1和node2之间没有元件连接），但是先不删除node2节点，只是将node2置空
    {
        for(int i = 0; i < adjacencyList[node2].size(); i++)
        {
            if(adjacencyList[node2][i]->n1 == node2)   //现将对应元件记录的连接node2改变为node1
                adjacencyList[node2][i]->n1 = node1;
            else
                adjacencyList[node2][i]->n2 = node1;
            adjacencyList[node1].push_back(adjacencyList[node2][i]);  //再将元件的指针放入node1的列表中
        }
        adjacencyList[node2].clear();      //清除node2的数据
    }

    void addSeriesComponent(int node, Component* targetCpt, Component* newCpt)     //在某个元件的某一端node加入一个新元件，使两个元件形成串联（这个过程中产生了一个新的节点，且串联的两个元件之间不存在其他分支）
    {
        //先处理节点
        auto it = find(adjacencyList[node].begin(),adjacencyList[node].end(),targetCpt);
        if(it != adjacencyList[node].end())
            adjacencyList[node].erase(it);
        adjacencyList[node].push_back(newCpt);

        int newNode = adjacencyList.size();
        adjacencyList[newNode].push_back(targetCpt);
        adjacencyList[newNode].push_back(newCpt);

        //再处理元件
        if(targetCpt->n2 == node)
            targetCpt->n2 = newNode;
        else
            targetCpt->n1 = newNode;
        newCpt->setNodes(newNode,node);

        numNodes = adjacencyList.size();
    }

    void addParallelComponent(Component* targetCpt, Component* newCpt)    //相对于目标元件添加并联新元件
    {
        int node1 = targetCpt->n1;
        int node2 = targetCpt->n2;
        newCpt->setNodes(node1,node2);
        adjacencyList[node1].push_back(newCpt);
        adjacencyList[node2].push_back(newCpt);
    }
    void addAllSourcesNormally(int countVS, int countCS)      //正常接入所有电源（包括电压源和电流源），“正常”代表不引入短路和开路,参数countVS和countCS表示已经接入电路的电源数量
    {
        int tmp = countVS;
        int countNode = 0;
        int rand_i;
        int rand_node;
        numNodes = adjacencyList.size();

        while(((countVS + countCS) < (numVoltageSources + numCurrentSources)) && (countNode < numNodes))   //第一步
        {
            if((countVS < numVoltageSources) && (countCS < numCurrentSources))   //当电压源和电流源都还有剩余时，随机选取接入电路
            {
                rand_i = rand() % 2;
                if((rand_i == 0) && ((countVS-tmp) != (numNodes-1)) && (countNode != (numNodes-1)))   //选取电压源((countVS-tmp) != (numNodes-1))判别式是因为如果取等说明n-1个节点都已经分别接到不同电压源的负极，此时最后一个节点再接到
                                                                //一个新的电压源的负极，那么整体上来看一定会形成电压源的回路，就形成短路了
                {
                    rand_node = countNode + 1 + (rand()%(numNodes-1-countNode));   //表示正极点rand_node随机取比当前节点countNode大的任意一个节点

                    adjacencyList[countNode].push_back(list_VS[countVS]);
                    adjacencyList[rand_node].push_back(list_VS[countVS]);
                    list_VS[countVS]->setNodes(rand_node,countNode);      //countNode连接电源负极
                    countVS++;
                    countNode++;
                }
                else      //选取电流源
                {
                    rand_node = rand() % numNodes; 
                    while(rand_node == countNode)                //对于电流源来说，因为电流源允许形成回路，所以正极点rand_node可以任意选取当前countNode以外的点
                        rand_node = rand() % numNodes;
                    adjacencyList[countNode].push_back(list_CS[countCS]);
                    adjacencyList[rand_node].push_back(list_CS[countCS]);
                    list_CS[countCS]->setNodes(rand_node,countNode);      //countNode连接电源负极
                    countCS++;
                    countNode++;
                }
            }
            else if(countVS < numVoltageSources)     //当电压源有剩余，电流源没剩余时
            {
                if((countVS-tmp) == (numNodes-1) || (countNode == (numNodes-1)))      
                    break;

                rand_node = countNode + 1 + (rand()%(numNodes-1-countNode));   //表示正极点rand_node随机取比当前节点countNode大的任意一个节点
                adjacencyList[countNode].push_back(list_VS[countVS]);
                adjacencyList[rand_node].push_back(list_VS[countVS]);
                list_VS[countVS]->setNodes(rand_node,countNode);      //countNode连接电源负极
                countVS++;
                countNode++;
            }
            else       //当电压源没剩余，电流源有剩余时
            {
                rand_node = rand() % numNodes;
                while(rand_node == countNode)
                    rand_node = rand() % numNodes;
                adjacencyList[countNode].push_back(list_CS[countCS]);
                adjacencyList[rand_node].push_back(list_CS[countCS]);
                list_CS[countCS]->setNodes(rand_node,countNode);      //countNode连接电源负极
                countCS++;
                countNode++;
            }
        }

        while((countVS + countCS) < (numVoltageSources + numCurrentSources))   //第一步后，电源还有未接入电路的，则进行第二步
        {
            if(countVS < numVoltageSources)    //先连接电压源
            {
                if((countVS > 0) && (countCS > 0))   //如果电压源和电流源都有已接入的，则随机选取
                {
                    rand_i = rand() % 2;
                    if(rand_i == 0)                //随机选择一个电压源串联
                    {
                        int rand_VS = rand() % countVS;
                        list_VS[countVS]->isShorted = list_VS[rand_VS]->isShorted;
                        addSeriesComponent(list_VS[rand_VS]->n2,list_VS[rand_VS],list_VS[countVS]);
                        countVS++;
                    }
                    else    //随机选择一个电流源串联（由于如果有多个电压源和电流源并联很可能间接导致电压源回路的形成，所以这里只让电压源与电流源串联）
                    {
                    
                        int rand_CS = rand() % countCS;
                        addSeriesComponent(list_CS[rand_CS]->n2,list_CS[rand_CS],list_VS[countVS]);
                        countVS++;
                    
                    }
                }
                else if(countVS > 0)   //已接入的电源只有电压源，那么随机选取一个已接入的电压源进行串联
                {
                    int rand_VS = rand() % countVS;
                    list_VS[countVS]->isShorted = list_VS[rand_VS]->isShorted;
                    addSeriesComponent(list_VS[rand_VS]->n2,list_VS[rand_VS],list_VS[countVS]);
                    countVS++;
                }
                else   //已接入的电源只有电流源，那么随机选取一个电流源进行串联（由于如果有多个电压源和电流源并联很可能间接导致电压源回路的形成，所以这里只让电压源与电流源串联）
                {
                    int rand_CS = rand() % countCS;
                    addSeriesComponent(list_CS[rand_CS]->n2,list_CS[rand_CS],list_VS[countVS]);
                    countVS++;
                }
            }
            else    //再连接电流源，电流源和已经接入电路的电压源或电流源并联或串联
            {
                if((countVS > 0) && (countCS > 0))   //如果电压源和电流源都有已接入的
                {
                    rand_i = rand() % 2;
                    if(rand_i == 0)   //随机选取一个电压源并联或串联
                    {
                        int tmp = rand() % 2;
                        int rand_VS = rand() % countVS;
                        if((tmp == 0) && (list_VS[rand_VS]->isShorted == false))   //串联,(list_VS[rand_VS]->isShorted == false)的判断是为了防止目标电压源的短路特性被破坏
                        {
                            addSeriesComponent(list_VS[rand_VS]->n2,list_VS[rand_VS],list_CS[countCS]);
                            countCS++;
                        }
                        else    //并联
                        {
                            addParallelComponent(list_VS[rand_VS],list_CS[countCS]);
                            countCS++;     
                        }
                    }
                    else        //随机选取一个电流源并联或串联
                    {
                        int tmp = rand() % 2;
                        int rand_CS = rand() % countCS;
                        if(tmp == 0)   //串联
                        {
                            addSeriesComponent(list_CS[rand_CS]->n2,list_CS[rand_CS],list_CS[countCS]);
                            countCS++;
                        }
                        else    //并联
                        {
                            addParallelComponent(list_CS[rand_CS],list_CS[countCS]);
                            countCS++;     
                        }
                    }
                }
                else if((countVS > 0))   //只有电压源有已接入的
                {
                    int tmp = rand() % 2;
                    int rand_VS = rand() % countVS;          //随机选取一个已接入的电压源
                    if((tmp == 0) && (list_VS[rand_VS]->isShorted == false))   //串联
                    {
                        addSeriesComponent(list_VS[rand_VS]->n2,list_VS[rand_VS],list_CS[countCS]);
                        countCS++;
                    }
                    else    //并联
                    {
                        addParallelComponent(list_VS[rand_VS],list_CS[countCS]);
                        countCS++;     
                    }
                }
                else    //只有电流源有已接入的
                {
                    int tmp = rand() % 2;
                    int rand_CS = rand() % countCS;
                    if(tmp == 0)   //串联
                    {
                        addSeriesComponent(list_CS[rand_CS]->n2,list_CS[rand_CS],list_CS[countCS]);
                        countCS++;
                    }
                    else    //并联
                    {
                        addParallelComponent(list_CS[rand_CS],list_CS[countCS]);
                        countCS++;     
                    }
                }
            }
        }

        numNodes = adjacencyList.size();
    }
    void addComponent(int n1, int n2, Component* component)  //添加元件（连接元件）
    {
        adjacencyList[n1].push_back(component);
        adjacencyList[n2].push_back(component);
    }
    
    void generateComponent()    //生成元件
    {
        //srand(time(0));  //取随机数种子

        list_VS = NULL; list_CS = NULL; list_R = NULL; list_C = NULL; list_L = NULL;

        if(numVoltageSources > 0)
        {
            list_VS = new VoltageSource*[numVoltageSources];
            for(int i = 0; i < numVoltageSources; i++)
                list_VS[i] = new VoltageSource((0.1+(rand()%100)*0.1), i + preNumVoltS);    //产生的电压源的值在0.1-10.0V之间（步长0.1V）
        }

        if(numCurrentSources > 0)
        {
            list_CS = new CurrentSource*[numCurrentSources];
            for(int i = 0; i < numCurrentSources; i++)
                list_CS[i] = new CurrentSource((0.1+(rand()%10)*0.1), i + preNumCurrS);     //产生的电流源的值在0.1-1A之间(步长0.1A)
        }

        if(numResistors > 0)
        {
            list_R = new Resistor*[numResistors];
            for(int i = 0; i < numResistors; i++)
                list_R[i] = new Resistor((50+(rand()%11)*5), i + preNumR);           //产生的电阻的阻值在50-100Ω之间（步长5Ω）
        }

        if(numCapacitors > 0)
        {
            list_C = new Capacitor*[numCapacitors];
            for(int i = 0; i < numCapacitors; i++)
                list_C[i] = new Capacitor((0.001+(rand()%100)*0.001),i + preNumC);   //产生的电容的阻值在0.001-0.1F之间（步长0.001F）
        }

        if(numInductors > 0)
        {
            list_L = new Inductor*[numInductors];
            for(int i = 0; i < numInductors; i++)
                list_L[i] = new Inductor((0.01+(rand()%100)*0.01),i + preNumL);        //产生的电感的阻值在0.01-1H之间（步长0.01H）
        }

    }
public:
    Circuit(int nVoltageSources, int nCurrentSources, int nResistors, int nCapacitors, int nInductors)  //输入元件数目
    {
        numVoltageSources = nVoltageSources;  //数据初始化
        numCurrentSources = nCurrentSources;
        numResistors = nResistors;
        numCapacitors = nCapacitors;
        numInductors = nInductors;
    }
    void addPreNumComponent (int preVoltS, int preCurrS, int preR, int preC, int preL)
    {
        preNumVoltS = preVoltS;
        preNumCurrS = preCurrS;
        preNumR = preR;
        preNumC = preC;
        preNumL = preL;
    }
    void addPreNumNodes (int preNodes)
    {
        preNumNodes = preNodes;
    }
    void generateCircuit(int isShort, bool isOpen) //根据电路是否有短路和开路调用不同函数生成circuit
    {
        generateComponent();
        if(isShort > 1) //短路节点数大于1，一定有RCL元件
        {
            if (!isOpen) generateRandomShortLoop(isShort);
            else generateRandomOpenloop(isShort);
            return;
        }
        if (numResistors != 0 || numCapacitors != 0 || numInductors != 0) //有RCL的情况
        {
            if(isShort == 1){
                if (isOpen)
                    generateRandomOpenloop(1);
                else
                    generateRandomShortLoop(1);
            }
            else{
                if(isOpen)
                    generateRandomOpenloop(0);
                else    
                    generateRandomNormalCircuit();
            }
            return;
        }

        //无RCL的情况

        bool isCurrOpen;  //标识开路的是否为电流源
        int n1,n2;
        if (isOpen){
            if (isShort > 0 && numVoltageSources + numCurrentSources < 2 || numVoltageSources < 1) {
                std::cerr <<("电源数不足（该环路既有短路又有开路，需要至少两个电源和至少一个电压源）"); 
                exit(1);
            }
            if(numCurrentSources != 0){
                numCurrentSources--;
                isCurrOpen = true;
            }
            else {
                numVoltageSources--;
                isCurrOpen = false;
            }
        }

        if (isShort == 0)
        {               
            numNodes = numVoltageSources + numCurrentSources;
            if (numVoltageSources != 0) //有电压源的情况
            {
                for (int i = 0; i < numCurrentSources ;i++){
                    addComponent(i, i+1, list_CS[i]);
                    list_CS[i] -> setNodes(i, i+1);
                }
                for (int i = numCurrentSources; i < numNodes -1 ;i++){
                    addComponent(i, i+1, list_VS[i - numCurrentSources]);
                    list_VS[i - numCurrentSources] -> setNodes(i, i+1);
                }
                //有开路电源连成一条线，否则连接成环
                if (isOpen){
                    addComponent(numNodes - 1, numNodes, list_VS[numVoltageSources - 1]);
                    list_VS[numVoltageSources - 1] -> setNodes(numNodes - 1, numNodes);
                    numNodes++;
                }
                else{
                    addComponent(numNodes - 1, 0, list_VS[numVoltageSources - 1]);
                    list_VS[numVoltageSources - 1] -> setNodes(numNodes - 1, 0);
                }
            }
            else //无电压源的情况,电流源顺次连接为环
            {
                for (int i = 0; i < numCurrentSources - 1 ;i++){
                    addComponent(i, i+1, list_CS[i]);
                    list_CS[i] -> setNodes(i, i+1);
                }
                addComponent(numNodes - 1, numNodes, list_CS[numCurrentSources - 1]);
                list_VS[numCurrentSources - 1] -> setNodes(numNodes - 1, numNodes);
            }    
        }
        else {
            if (numVoltageSources ==1){
                n1 = 0;
                n2 = 0;
                numNodes = 1;
                addComponent(n1, n2, list_VS[0]);
                list_VS[0]->setNodes(n1,n2);
            }
            else if(numVoltageSources > 1){
                n1 = 0;
                n2 = 1;
                numNodes = 2;
                for (int i = 0; i < numVoltageSources;i++){
                    addComponent(n1, n2, list_VS[i]);
                    list_VS[i]->setNodes(n1,n2);
                }
            
            }
            for (int i = 0; i < numCurrentSources ;i++){
                    addComponent(n1, n2, list_CS[i]);
                    list_CS[i]->setNodes(n1,n2);                
            }
        }
        //开路的电源一端连入电路，一端悬空
        if(isOpen){
            int rand_node = rand() % numNodes;
            if (isCurrOpen) {
                list_CS[numCurrentSources]->setNodes(rand_node, numNodes);
                numCurrentSources++;
            }
            else {
                list_VS[numVoltageSources]->setNodes(rand_node, numNodes);
                numVoltageSources++;
            }

            numNodes++;
        }
    }
    void generateRandomNormalCircuit()  //根据给定的元件数目随机生成Circuit     -------------------------------------这里不处理RCL总数为0的情况,规定电源数大于0且RCL总数大于0
    {
        //思路：在一个Circuit中，我们规定RCL允许有一端是悬空的，不能两端都悬空，而对于电源（电流源和电压源）来说，如果不是开路和短路的情况，电源必须接到RCL的两端
        //      所以我们随机生成Circuit的步骤如下：1.根据R、C、L的总数目+1得到最大的节点数maxNode 2.接入RCL：产生RCL并分别随机选取两个节点连接 3.在adjacencyList中遍历各个节点，如果发现某个节点
        //      未连接元件，那么说明这个节点无效，删除这个节点；如果只连接了一个元件，那么说明这个节点是一个悬空节点，对应元件的这一端悬空，检查这个元件的另外一个节点是否悬空，如果是的话就随机取两个悬空节点
        //      其一与两者之外的任意一个节点“合并”（“合并”即将现有节点改为目标节点） 4.接入电源：根据要生成的电源的数目，生成电源，依次随机接入两个节点，这样可以保证电源不开路且不短路
        //对于在邻接表上删除某节点的操作的说明：假设待删除的结点为j，可以暂时将adjcencyList[j]清空，等到所有删除操作结束后借助一个临时的邻接表，遍历原邻接表，对于节点i如果adjacencyList[i]不为空，则将相关信息复制，得到的结果
        //copy回原来的邻接表，这样就得到了最终的全是有效节点的邻接表


        srand(time(0));  //取随机数种子
        //先完成RCL元件的连接
        numNodes = numResistors + numCapacitors + numInductors + 1;  //最坏情况下，每个RCL元件都有一端悬空，那么就有n+1个节点 
        //连接电阻
        for (int i = 0; i < numResistors; i++) 
        {
            int n1 = rand() % numNodes;
            int n2 = rand() % numNodes;
            while(n1 == n2)     //防止元件发生“自环”，即防止两端接到一起
            {
                n1 = rand() % numNodes;
                n2 = rand() % numNodes;
            } 
            addComponent(n1, n2, list_R[i]);
            list_R[i]->setNodes(n1,n2);
        }
        //连接电容
        for (int i = 0; i < numCapacitors; i++) 
        {
            int n1 = rand() % numNodes;
            int n2 = rand() % numNodes;
            while(n1 == n2)     //防止元件发生“自环”，即防止两端接到一起
            {
                n1 = rand() % numNodes;
                n2 = rand() % numNodes;
            } 
            addComponent(n1, n2, list_C[i]);
            list_C[i]->setNodes(n1,n2);
        }
        //连接电感
        for (int i = 0; i < numInductors; i++) 
        {
            int n1 = rand() % numNodes;
            int n2 = rand() % numNodes;
            while(n1 == n2)     //防止元件发生“自环”，即防止两端接到一起
            {
                n1 = rand() % numNodes;
                n2 = rand() % numNodes;
            } 
            addComponent(n1, n2, list_L[i]);
            list_L[i]->setNodes(n1,n2);
        }

        //接下来对悬空节点和空节点进行处理
        if(numNodes > 2)   //numNodes==2 即表明只有一个RCL元件，那么就允许这个唯一的RCL元件两端都是悬空的; numNodes>2时，遍历每个节点，发现悬空节点则做处理，发现空节点则删除
        {
            int emptyNode[numNodes] = {0};   //标定每个节点是否为空节点，0不是空节点，1是空节点
            for(int i = 0; i < numNodes; i++)   //第一次遍历，标记空节点，但先不删除
                if(adjacencyList[i].size() == 0)
                    emptyNode[i] = 1;

            for(int i = 0; i < numNodes; i++)  //第二次遍历，处理悬空节点
                if(adjacencyList[i].size() == 1)  //这个节点只连接了一个RCL元件，是一个悬空节点 
                {
                    Component* temp_Cmpt = adjacencyList[i][0];
                    int temp_n = (i==temp_Cmpt->n1)?temp_Cmpt->n2:temp_Cmpt->n1;  //找到对应元件的另外一个节点
                    if(adjacencyList[temp_n].size() == 1)   //如果另外一端也是悬空节点
                    {
                        int temp_i;
                        bool loop = true; 
                        while(loop)
                        {
                            loop = false;
                            temp_i = rand()%numNodes;  //取随机数
                            if(temp_i == i || temp_i == temp_n || emptyNode[temp_i] == 1)   //如果取到的节点和原来两个节点重复或者取到的节点是空节点，那么重新取随机数
                                loop = true;
                        }
                        mergeNodes(temp_i,temp_n);    //取到符合条件的节点，把原节点与其归并(只留下符合条件的节点)(现在还未删除原节点)
                    }
                }
            deleteEmptyNodes();      //正式删除空节点
            numNodes = adjacencyList.size();    //更新实际节点数
        }

        connectSeparateCircuit();       //将图中所有的独立连通分量都连接起来，成为一个大的连通分量
        numNodes = adjacencyList.size();    //更新实际节点数

        //现添加电流源和电压源
        //为了避免分立Circuit的问题，我们直接避免电源的负极连接在一起，那么分为两步：1.一个个接入电源，使电源的负极端固定在不同的已有节点上，另一端随机，这样这一步接入的最大电源数等于节点数
        //                                                                    2.第1步后剩余电源中：电压源与已经加入的电压源串联 或者 与已经加入的电流源串联；电流源与已经加入的电压源或电流源串联或并联
        addAllSourcesNormally(0,0);
    }
    void generateRandomShortLoop(int nShort)    //nShort的上限为RCL的个数之和+1（RCL个数之和为0的情况这里不考虑）, 而且nShort也要小于等于电压源的数目  
    {
        if(nShort > (numResistors + numCapacitors + numInductors + 1))   
        {
            printf("nShort must satisfy: nShort <= nR+nC+nL+1 .\n");
            exit(1);   //程序异常终止
            return;
        }
        if(nShort > numVoltageSources)
        {
            printf("nShort must satisfy: nShort <= nVS .\n");
            exit(1);
            return;
        }

        srand(time(0));  //取随机数种子
  
        int countR = 0;        //count变量辅助RCL的连接
        int countC = 0;
        int countL = 0;

        int rand_i;
        int decision;   //辅助接入RCL的判断，0代表接入R，1代表接入C，2代表接入L，规定decision只能取0,1,2
        numNodes = 0;   //初始化电路内节点数为0
        
        //随机接入RCL，保证每接入一个RCL元件，电路中多一个节点（其中第一个接入的RCL元件为电路添加2个节点）因此，由于nShort > (numResistors + numCapacitors + numInductors + 1)
        //已经在最开始作判断为不可能，以下while循环的退出条件中 ((countR + countC + countL) >= (numResistors + numCapacitors + numInductors)) 且 (numNodes < nShort) 是不可能存在的
        while((numNodes < nShort) && ((countR + countC + countL) < (numResistors + numCapacitors + numInductors)))
        {
            rand_i = rand() % 3;    //随机选择接入RCL
            //先进行决策
            switch (rand_i)
            {
            case 0:   //选择接入R
                if((numResistors-countR) != 0)    //有R
                    decision = 0;
                else     //没有R
                {
                    if(((numCapacitors-countC) != 0) && ((numInductors-countL) != 0))
                    {
                        rand_i = rand() % 2;
                        if(rand_i == 0)   //选择接入C
                            decision = 1;
                        else     //选择接入L
                            decision = 2;
                    }
                    else if(((numCapacitors-countC) != 0) && ((numInductors-countL) == 0))
                        decision = 1;
                    else
                        decision = 2;
                }
                break;
            case 1:   //选择接入C
                if((numCapacitors-countC) != 0)    //有C
                    decision = 1;
                else     //没有C
                {
                    if(((numResistors-countR) != 0) && ((numInductors-countL) != 0))
                    {
                        rand_i = rand() % 2;
                        if(rand_i == 0)   //选择接入R
                            decision = 0;
                        else     //选择接入L
                            decision = 2;
                    }
                    else if(((numResistors-countR) != 0) && ((numInductors-countL) == 0))
                        decision = 0;
                    else
                        decision = 2;
                }
                break;
            case 2:   //选择接入L
                if((numInductors-countL) != 0)    //有L
                    decision = 2;
                else     //没有L
                {
                    if(((numResistors-countR) != 0) && ((numCapacitors-countC) != 0))
                    {
                        rand_i = rand() % 2;
                        if(rand_i == 0)   //选择接入R
                            decision = 0;
                        else     //选择接入C
                            decision = 1;
                    }
                    else if(((numResistors-countR) != 0) && ((numCapacitors-countC) == 0))
                        decision = 0;
                    else
                        decision = 1;
                }
                break;
            }
            //再进行连接
            if(numNodes == 0)   //接入第一个RCL元件时，一定会产生2个节点，这种情况更加特殊，单独处理
            {
                switch (decision)
                {
                case 0:
                    addComponent(0,1,list_R[countR]);
                    list_R[countR]->setNodes(0,1);
                    countR++;
                    numNodes = numNodes+2;
                    break;
                case 1:
                    addComponent(0,1,list_C[countC]);
                    list_C[countC]->setNodes(0,1);
                    countC++;
                    numNodes = numNodes+2;
                    break;
                case 2:
                    addComponent(0,1,list_L[countL]);
                    list_L[countL]->setNodes(0,1);
                    countL++;
                    numNodes = numNodes+2;
                    break;
                }
            }
            else    //一般情况
            {
                switch (decision)
                {
                case 0:
                {
                    int node = rand() % numNodes;  //随机取一个电路中的节点作为一端， 另一端为一个新的悬空节点
                    addComponent(node,numNodes,list_R[countR]);
                    list_R[countR]->setNodes(node,numNodes);
                    countR++;
                    numNodes++;
                    break;
                }
                case 1:
                {
                    int node = rand() % numNodes;  //随机取一个电路中的节点作为一端， 另一端为一个新的悬空节点
                    addComponent(node,numNodes,list_C[countC]);
                    list_C[countC]->setNodes(node,numNodes);
                    countC++;
                    numNodes++;
                    break;
                }
                case 2:
                {
                    int node = rand() % numNodes;  //随机取一个电路中的节点作为一端， 另一端为一个新的悬空节点
                    addComponent(node,numNodes,list_L[countL]);
                    list_L[countL]->setNodes(node,numNodes);
                    countL++;
                    numNodes++;
                    break;
                }
                }
            }

        }
        if((numNodes >= nShort) && ((countR + countC + countL) < (numResistors + numCapacitors + numInductors)))   //还剩余RCL未接入
        {
            int maxNodes = numNodes + (numResistors + numCapacitors + numInductors) - (countR + countC + countL);
            numNodes = maxNodes;
            //连接电阻
            for (; countR < numResistors; countR++) 
            {
                int n1 = rand() % maxNodes;
                int n2 = rand() % maxNodes;
                while(n1 == n2)     //防止元件发生“自环”，即防止两端接到一起
                {
                    n1 = rand() % maxNodes;
                    n2 = rand() % maxNodes;
                } 
                addComponent(n1, n2, list_R[countR]);
                list_R[countR]->setNodes(n1,n2);
            }
            //连接电容
            for (; countC < numCapacitors; countC++) 
            {
                int n1 = rand() % maxNodes;
                int n2 = rand() % maxNodes;
                while(n1 == n2)     //防止元件发生“自环”，即防止两端接到一起
                {
                    n1 = rand() % maxNodes;
                    n2 = rand() % maxNodes;
                } 
                addComponent(n1, n2, list_C[countC]);
                list_C[countC]->setNodes(n1,n2);
            }
            //连接电感
            for (; countL < numInductors; countL++) 
            {
                int n1 = rand() % maxNodes;
                int n2 = rand() % maxNodes;
                while(n1 == n2)     //防止元件发生“自环”，即防止两端接到一起
                {
                    n1 = rand() % maxNodes;
                    n2 = rand() % maxNodes;
                } 
                addComponent(n1, n2, list_L[countL]);
                list_L[countL]->setNodes(n1,n2);
            }

            //接下来对悬空节点和空节点进行处理
            if(numNodes > 2)   //numNodes==2 即表明只有一个RCL元件，那么就允许这个唯一的RCL元件两端都是悬空的; numNodes>2时，遍历每个节点，发现悬空节点则做处理，发现空节点则删除
            {
                int emptyNode[numNodes] = {0};   //标定每个节点是否为空节点，0不是空节点，1是空节点
                for(int i = 0; i < numNodes; i++)   //第一次遍历，标记空节点，但先不删除
                    if(adjacencyList[i].size() == 0)
                        emptyNode[i] = 1;

                for(int i = 0; i < numNodes; i++)  //第二次遍历，处理悬空节点
                    if(adjacencyList[i].size() == 1)  //这个节点只连接了一个RCL元件，是一个悬空节点 
                    {
                        Component* temp_Cmpt = adjacencyList[i][0];
                        int temp_n = (i==temp_Cmpt->n1)?temp_Cmpt->n2:temp_Cmpt->n1;  //找到对应元件的另外一个节点
                        if(adjacencyList[temp_n].size() == 1)   //如果另外一端也是悬空节点
                        {
                            int temp_i;
                            bool loop = true; 
                            while(loop)
                            {
                                loop = false;
                                temp_i = rand()%numNodes;  //取随机数
                                if(temp_i == i || temp_i == temp_n || emptyNode[temp_i] == 1)   //如果取到的节点和原来两个节点重复或者取到的节点是空节点，那么重新取随机数
                                    loop = true;
                            }
                            mergeNodes(temp_i,temp_n);    //取到符合条件的节点，把原节点与其归并(只留下符合条件的节点)(现在还未删除原节点)
                        }
                    }
                deleteEmptyNodes();      //正式删除空节点
                numNodes = adjacencyList.size();    //更新实际节点数
            }

            connectSeparateCircuit();       //将图中所有的独立连通分量都连接起来，成为一个大的连通分量
            numNodes = adjacencyList.size();    //更新实际节点数
        }

        //现在一定满足numNodes >= nShort
        //先连接电压源
        int countVS = 0;
        vector<int> Node_list;      //将所有节点放入一个容器中
        for(int i = 0; i < numNodes; i++)
            Node_list.push_back(i);
        random_shuffle(Node_list.begin(),Node_list.end());   //打乱顺序，以便随机取节点
        for(int i = 0; i < nShort; i++)   //每次随机取一个节点并且将一个电压源短接在这里,形成一个短路节点对,由于nShort <= nVoltageSources,所以每个循环一定都可以取到电压源
        {
            addComponent(Node_list[i],Node_list[i],list_VS[countVS]);
            list_VS[countVS]->setNodes(Node_list[i],Node_list[i]);
            list_VS[countVS]->isShorted = true;
            countVS++;
        }
        //如果还有多余的电压源,那就和电流源一样，正常进行连接
        addAllSourcesNormally(countVS,0);
    }
    void generateRandomOpenloop(int nShort)   //生成带开路电源的电路，nShort是短路节点对数，如果大于0代表这个电路短路。
    {                                         //这里思路是先保留一个电压源或电流源，其他电路元件正常生成正常电路，最后再随机加入那个电源（一端悬空）
        if((numVoltageSources < nShort) || ((numVoltageSources + numCurrentSources) < (nShort + 1)))
        {
            printf("it must be satisfied: (numVoltageSources >= nShort) && ((numVoltageSources + numCurrentSources) >= (nShort + 1))");
            exit(1);
        }
        int keepnVS = numVoltageSources;   //先保留电压源和电流源数目的原始值
        int keepnCS = numCurrentSources;
        int key;    //标记
        if((numVoltageSources > 0) && (numCurrentSources > 0))   //这里随机取一个电源保留
        {
            int rand_i = rand() % 2;    //二选一
            if((rand_i == 0) && (numVoltageSources > nShort))   //如果(numVoltageSources == nShort)那所有的电压源都要拿来短路，不能取一个拿来开路
            {
                key = 0;
                numVoltageSources = numVoltageSources - 1;
            }
            else
            {
                key = 1;
                numCurrentSources = numCurrentSources - 1;
            }
        }
        else if((numVoltageSources > 0) && (numCurrentSources == 0))
        {
            key = 0;
            numVoltageSources = numVoltageSources - 1;
        }
        else
        {
            key = 1;
            numCurrentSources = numCurrentSources - 1;
        }
        //生成电路
        if(nShort == 0)
            generateRandomNormalCircuit();
        else
            generateRandomShortLoop(nShort);
        
        numVoltageSources = keepnVS;    //恢复
        numCurrentSources = keepnCS;

        numNodes = adjacencyList.size();
        int rand_node = rand() % numNodes;
        if(key == 0)
        {
            addComponent(rand_node,numNodes,list_VS[numVoltageSources-1]);
            list_VS[numVoltageSources-1]->setNodes(rand_node,numNodes);
        }
        else
        {
            addComponent(rand_node,numNodes,list_CS[numCurrentSources-1]);
            list_CS[numCurrentSources-1]->setNodes(rand_node,numNodes);
        }

        numNodes = adjacencyList.size();
    }

    //获取电路中的节点数
    int getNodes()
    {
        return numNodes;
    }

    void printNetlist(std::ostream& os = std::cout)  //接受一个输出流参数
    {
        for(int i = 0; i < numVoltageSources; i++)
            os << list_VS[i]->getNetlistEntry(preNumNodes) << endl;
        for(int i = 0; i < numCurrentSources; i++)
            os << list_CS[i]->getNetlistEntry(preNumNodes) << endl;
        for(int i = 0; i < numResistors; i++)
            os << list_R[i]->getNetlistEntry(preNumNodes) << endl;
        for(int i = 0; i < numCapacitors; i++)
            os << list_C[i]->getNetlistEntry(preNumNodes) << endl;
        for(int i = 0; i < numInductors; i++)
            os << list_L[i]->getNetlistEntry(preNumNodes) << endl;
        os<< endl;
    }

};
//为每个Circuit分配元件数目，并添加到容器里
//分配策略为平均分配加随机分配
void InitVector(int nVoltS, int nCurrS, int nR, int nC, int nL, int nShort, int nLoop,bool bOpen, vector<Circuit*>& vec)
{
    int unusedVoltS,unusedCurrS,unusedR,unusedC,unusedL;
    unusedVoltS = nVoltS;
    unusedCurrS = nCurrS;
    unusedR = nR;
    unusedC = nC;
    unusedL = nL;

    int numVoltageSources;  //电压源参数
    int numCurrentSources;  //电流源参数
    int numResistors;    //电阻参数
    int numCapacitors;    //电容参数
    int numInductors;     //电感参数
    int Short; 
    bool Open = false;
    int commonCircuit = nLoop - nShort;
    int unusedShort = nShort;

    
    for (int i = nLoop; i > 0;i--){
        //短路大于回路数
        if (nShort > nLoop)
        {
            
            int nComponent;
            Short = unusedShort /i;
            //有开路时，提前保存一个电压源用于开路
            if (bOpen && nCurrS == 0 && i == nLoop)
                unusedVoltS = nVoltS = nVoltS - 1;

            if(i == 1){
                numResistors = unusedR;
                numCapacitors = unusedC;
                numInductors = unusedL;
                if(bOpen && nCurrS == 0){  //开路，释放提前保存的电压源
                    numVoltageSources = unusedVoltS;
                    nVoltS = nVoltS + 1;
                }
                else numVoltageSources = unusedVoltS;
                numCurrentSources = unusedCurrS; 
                Open = bOpen;
            }
            else{
                //剩余元件数/剩余circuit数 作为分配元件数；为保证短路条件满足，R,C,L要额外添加约束
                numResistors = unusedR / i;
                numCapacitors = (unusedR + unusedC) / i - numResistors;
                numInductors = (unusedR + unusedC + unusedL) / i - numResistors - numCapacitors;

                numVoltageSources = unusedVoltS / i;
                numCurrentSources = unusedCurrS / i;
                nComponent = numResistors + numCapacitors + numInductors;

                //为保证短路条件满足，缺少的R,C,L要额外补上
                int x = Short - nComponent - 1;
                while (x > 0){
                    if(unusedR - numResistors != 0){
                        numResistors += (x > unusedR - numResistors? unusedR - numResistors:x);
                        x-= unusedR - numResistors;
                        continue;
                    }
                    if(unusedC - numCapacitors != 0){
                        numCapacitors += (x > unusedC - numCapacitors? unusedC - numCapacitors:x);
                        x -= unusedC - numCapacitors;
                        continue;
                    }
                    if(unusedL - numInductors != 0){
                        numInductors += (x > unusedL - numInductors? unusedL - numInductors:x);
                        x -= unusedL - numInductors;
                        if(x > 0) std::cerr << "No enough Component to satisfy Short"<< endl;
                        break;
                    }

                }
            }
        }
        else  //短路小于回路数情况
        {
            
            if(i == 1){  //最后一个circuit，放入所有器件
                numResistors = unusedR;
                numCapacitors = unusedC;
                numInductors = unusedL;
            }
            else if(unusedR > i || unusedC >i || unusedL >i) //器件富足（至少有一种器件数量比剩下的circuit数多），随机分配,保证一定有器件
            {
                if (unusedR > i)
                    numResistors = 1 + rand() % (unusedR - i);
                else numResistors = 0;
                if (unusedC > i)
                    numCapacitors = 1 + rand() % (unusedC - i);
                else numCapacitors = 0;
                if (unusedL > i)
                    numInductors = 1 + rand() % (unusedL - i);
                else numInductors = 0;
            }
            else if(unusedR + unusedC + unusedL < i){ //器件数量比circuit数量少则不分配
                numResistors = numCapacitors = numInductors = 0;
            }
            else  //一般情况保证一定有一个器件
            {
                if(unusedR != 0){
                    numResistors = 1;
                    numCapacitors = numInductors = 0;
                }
                else if (unusedC != 0){
                    numCapacitors = 1;
                    numResistors = numInductors = 0;
                }
                else{
                    numInductors = 1; 
                    numResistors = numCapacitors = 0;
                }
            }
             //短路需要至少一个电压源
            if (i > commonCircuit && unusedVoltS < i){
                numVoltageSources = 1;
                numCurrentSources = unusedCurrS /i; 
            }
            else if (unusedVoltS>= i || unusedCurrS >=i) //电源富足，剩余电源数/剩余circuit数 作为分配电源数
            { 
                numVoltageSources = unusedVoltS/i;           
                numCurrentSources = unusedCurrS /i;           
            }
            else //至少保证每个回路都有电源
            {
                if(unusedVoltS>= unusedCurrS) {
                    numVoltageSources = 0;
                    numCurrentSources = 1;
                }
                else{
                    numVoltageSources = 1;
                    numCurrentSources = 0;
                }
            }
            if (i > commonCircuit) Short = 1;
            else Short = 0;
            if (i == 1 && bOpen == true) Open = true;  //开路默认放在最后一个circuit
        }
        Circuit *circuit = new Circuit(numVoltageSources, numCurrentSources, numResistors, numCapacitors, numInductors);  //新建对象
        circuit->addPreNumComponent(nVoltS -unusedVoltS, nCurrS-unusedCurrS, nR-unusedR, nC-unusedC, nL-unusedL); //添加已使用的元件数
        circuit->generateCircuit(Short, Open); //传递短路和开路参数，生成电路
        vec.push_back(circuit);
        //circuit->printNetlist();
        //未使用的元件数更新
        unusedVoltS -= numVoltageSources;
        unusedCurrS -= numCurrentSources;
        unusedR -= numResistors;
        unusedC -= numCapacitors;
        unusedL -= numInductors;  
        unusedShort -= Short;

    }

}

int main() {
    int nVoltS, nCurrS, nR, nC, nL, nShort, nLoop;
    bool bOpen; 
    vector<Circuit*> circuitVec;
    srand(time(0));  //取随机数种子

    if (readParameter(nVoltS,nCurrS, nR, nC, nL, nShort, nLoop,bOpen)) return 1;  //从文件中读取参数，若报错则直接退出

    InitVector(nVoltS, nCurrS, nR, nC, nL,nShort, nLoop, bOpen, circuitVec);
    //InitVector(24,15,0,0,0,10,10,true,circuitVec);

    std::ofstream out("netlistDump.sp");
    if (!out.is_open()) {
        std::cerr << "无法打开文件！" << std::endl;
        return 1;
    }
    int preNodes = 1;
    for (auto& obj : circuitVec) {
        obj->addPreNumNodes(preNodes); //为circuit读入已使用节点数
        obj->printNetlist(out);        //打印
        preNodes += obj->getNodes();  //已使用节点数更新
    }

    return 0;
}
